前一篇結尾講到了物件的傳參考的特性,但有時候我們希望屬性和值是被直接複製一份,並非是直接指向的
淺複製(shallow copy)
如果用一般比較傳統的方式,會使用 for in 的作法:
var person = {
name: 'Jerry',
members: {
father: 'John',
mother: 'Mary'
}
};
var person2 = {};
for(var key in person){
person2[key] = person[key]
}
這時候如果在 person2 更改 name 屬性,person 是不會被影響的,這是因為當命名 person2 為空物件的時候,已經把它指向另外一個記憶體空間,接著把 person 的屬性用 for 迴圈一一的傳遞給 person2,就可以把一個物件複製
當然 ES6 提供了一個不錯的方法可以做使用 Object.assign()
,方法內是一個空物件跟要被複製的物件變數:
var person2 = Object.assign({}, person);
這個方法結果會跟上面是一樣的,只是更為簡潔好用
上面所講的都是淺複製,為什麼是淺複製呢 ?
因為當我們嘗試去更改 person2 的 members 物件屬性的內部屬性時,person 的 members 屬性也被做更動了,這是因為 members 這個物件屬性,它也是一個物件,所以也是獨立的記憶體空間,即使複製了,指向的位置依然沒有變動
所以為了這種多層次的物件,有另外一種複製的方式
深複製(deep copy)
聽起來雖然很深奧,但其實只是運用了 JavaScript 的轉字串跟轉物件的方式而已
// 首先先把物件格式轉成字串
JSON.stringify(person);
// 再轉回去物件,並賦予一個變數
var person3 = JSON.parse(JSON.stringify(person));
轉完之後,先來更改一下 person3 的物件屬性 members 的 mother 屬性person3.members.mother = 'Anna';
再用 console 分別查看 person 和 person3 的物件屬性 members 的 mother 屬性
console.log(person.members.mother, person3.members.mother);
// Mary, Anna
就會發現資料已經不會互相影響了,進一步一樣可以用 ===
來檢查
console.log(person.members === person3.members);
// false
這樣彼此的 members 物件屬性就分別指向不同的記憶體空間,也完成了物件屬性的複製
這就是深複製(deep copy)